home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / pygtk / 2.0 / codegen / docextract.py < prev    next >
Text File  |  2006-01-20  |  6KB  |  186 lines

  1. # -*- Mode: Python; py-indent-offset: 4 -*-
  2. '''Simple module for extracting GNOME style doc comments from C
  3. sources, so I can use them for other purposes.'''
  4.  
  5. import sys, os, string, re
  6.  
  7. __all__ = ['extract']
  8.  
  9. class FunctionDoc:
  10.     def __init__(self):
  11.     self.name = None
  12.     self.params = []
  13.     self.description = ''
  14.     self.ret = ''
  15.     def set_name(self, name):
  16.     self.name = name
  17.     def add_param(self, name, description):
  18.     if name == '...':
  19.         name = 'Varargs'
  20.     self.params.append((name, description))
  21.     def append_to_last_param(self, extra):
  22.     self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra)
  23.     def append_to_named_param(self, name, extra):
  24.         for i in range(len(self.params)):
  25.             if self.params[i][0] == name:
  26.                 self.params[i] = (name, self.params[i][1] + extra)
  27.                 return
  28.         # fall through to adding extra parameter ...
  29.         self.add_param(name, extra)
  30.     def append_description(self, extra):
  31.     self.description = self.description + extra
  32.     def append_return(self, extra):
  33.     self.ret = self.ret + extra
  34.  
  35.     def get_param_description(self, name):
  36.         for param, description in self.params:
  37.             if param == name:
  38.                 return description
  39.         else:
  40.             return ''
  41.  
  42. comment_start_pat = re.compile(r'^\s*/\*\*\s')
  43. comment_end_pat = re.compile(r'^\s*\*+/')
  44. comment_line_lead = re.compile(r'^\s*\*\s*')
  45. funcname_pat = re.compile(r'^(\w+)\s*:?')
  46. return_pat = re.compile(r'^(returns:|return\s+value:|returns\s*)(.*\n?)$',
  47.             re.IGNORECASE)
  48. param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$')
  49.  
  50. def parse_file(fp, doc_dict):
  51.     line = fp.readline()
  52.     in_comment_block = 0
  53.     while line:
  54.     if not in_comment_block:
  55.         if comment_start_pat.match(line):
  56.         in_comment_block = 1
  57.         cur_doc = FunctionDoc()
  58.         in_description = 0
  59.         in_return = 0
  60.         line = fp.readline()
  61.         continue
  62.     
  63.     # we are inside a comment block ...
  64.     if comment_end_pat.match(line):
  65.         if not cur_doc.name:
  66.         sys.stderr.write("no function name found in doc comment\n")
  67.         else:
  68.         doc_dict[cur_doc.name] = cur_doc
  69.         in_comment_block = 0
  70.         line = fp.readline()
  71.         continue
  72.  
  73.     # inside a comment block, and not the end of the block ...
  74.     line = comment_line_lead.sub('', line)
  75.     if not line: line = '\n'
  76.  
  77.     if not cur_doc.name:
  78.         match = funcname_pat.match(line)
  79.         if match:
  80.         cur_doc.set_name(match.group(1))
  81.     elif in_return:
  82.         match = return_pat.match(line)
  83.         if match:
  84.         # assume the last return statement was really part of the
  85.         # description
  86.         cur_doc.description = cur_doc.description + return_start + \
  87.                       cur_doc.ret
  88.         return_start = match.group(1)
  89.         cur_doc.ret = match.group(2)
  90.         else:
  91.         cur_doc.append_return(line)
  92.     elif in_description:
  93.         if line[:12] == 'Description:':
  94.         line = line[12:]
  95.         match = return_pat.match(line)
  96.         if match:
  97.         in_return = 1
  98.         return_start = match.group(1)
  99.         cur_doc.append_return(match.group(2))
  100.         else:
  101.         cur_doc.append_description(line)
  102.     elif line == '\n':
  103.         # end of parameters
  104.         in_description = 1
  105.     else:
  106.         match = param_pat.match(line)
  107.         if match:
  108.         param = match.group(1)
  109.         desc = match.group(2)
  110.                 if param == 'returns':
  111.                     cur_doc.ret = desc
  112.                 else:
  113.                     cur_doc.add_param(param, desc)
  114.         else:
  115.         # must be continuation
  116.         try:
  117.                     if param == 'returns':
  118.                         cur_doc.append_return(line)
  119.                     else:
  120.                         cur_doc.append_to_last_param(line)
  121.         except:
  122.             sys.stderr.write('something weird while reading param\n')
  123.     line = fp.readline()
  124.  
  125. def parse_dir(dir, doc_dict):
  126.     for file in os.listdir(dir):
  127.     if file in ('.', '..'): continue
  128.     path = os.path.join(dir, file)
  129.     if os.path.isdir(path):
  130.         parse_dir(path, doc_dict)
  131.     if len(file) > 2 and file[-2:] == '.c':
  132.         parse_file(open(path, 'r'), doc_dict)
  133.  
  134. def extract(dirs, doc_dict=None):
  135.     if not doc_dict: doc_dict = {}
  136.     for dir in dirs:
  137.     parse_dir(dir, doc_dict)
  138.     return doc_dict
  139.  
  140. tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$')
  141. def parse_tmpl(fp, doc_dict):
  142.     cur_doc = None
  143.  
  144.     line = fp.readline()
  145.     while line:
  146.         match = tmpl_section_pat.match(line)
  147.         if match:
  148.             cur_doc = None  # new input shouldn't affect the old doc dict
  149.             sect_type = match.group(1)
  150.             sect_name = match.group(2)
  151.  
  152.             if sect_type == 'FUNCTION':
  153.                 cur_doc = doc_dict.get(sect_name)
  154.                 if not cur_doc:
  155.                     cur_doc = FunctionDoc()
  156.                     cur_doc.set_name(sect_name)
  157.                     doc_dict[sect_name] = cur_doc
  158.         elif line == '<!-- # Unused Parameters # -->\n':
  159.             cur_doc = None # don't worry about unused params.
  160.         elif cur_doc:
  161.             if line[:10] == '@Returns: ':
  162.                 if string.strip(line[10:]):
  163.                     cur_doc.append_return(line[10:])
  164.             elif line[0] == '@':
  165.                 pos = string.find(line, ':')
  166.                 if pos >= 0:
  167.                     cur_doc.append_to_named_param(line[1:pos], line[pos+1:])
  168.                 else:
  169.                     cur_doc.append_description(line)
  170.             else:
  171.                 cur_doc.append_description(line)
  172.  
  173.         line = fp.readline()
  174.  
  175. def extract_tmpl(dirs, doc_dict=None):
  176.     if not doc_dict: doc_dict = {}
  177.     for dir in dirs:
  178.         for file in os.listdir(dir):
  179.             if file in ('.', '..'): continue
  180.             path = os.path.join(dir, file)
  181.             if os.path.isdir(path):
  182.                 continue
  183.             if len(file) > 2 and file[-2:] == '.sgml':
  184.                 parse_tmpl(open(path, 'r'), doc_dict)
  185.     return doc_dict
  186.